package org.mtmi.ui.controls.midi;

import java.util.Collection;
import java.util.Iterator;

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.mtmi.ui.IMG;
import org.mtmi.ui.M;
import org.mtmi.ui.controls.Int127Menu;
import org.mtmi.ui.controls.listeners.MenuSelectionListener;
import org.mtmi.ui.drawables.IDrawable;
import org.mtmi.ui.scenes.COLOR;
import org.mtmi.ui.scenes.FontManager;
import org.mtmi.ui.scenes.SceneManager;

/**
 * This action display a menu to choose a number from 0..255,
 * and change the MIDI velocity of IMidiVelocity (or collection of).
 */
public class ChangeMidiVelocityAction extends AbstractRetargettableMidiAction
{
	
	public ChangeMidiVelocityAction() {
		super( null );
	}
	
	/** @return instrument number shared by current target, -1 otherwise */
	private int getVelocity() {
		if( target instanceof IMidiVelocity ) {
			//can display midi channel
			return ((IMidiVelocity)target).getMidiVelocity();
		} else {
			//check if all control have same midi channel:
			Collection<?> c = (Collection<?>)target;
			int velocity=-1;
			boolean f=true;
			for( Iterator<?> I = c.iterator(); I.hasNext(); ) {
				int v = ((IMidiVelocity)I.next()).getMidiVelocity();
				if( f ) {
					velocity = v; f=false;
				} else {
					if( v!=velocity ) {
						//not shared by all elements of list
						return -1;
					}
				}
			}
			return velocity;
		}
	}
	
	@Override
	public IDrawable getImage() {
		int ins = getVelocity();
		if( ins < 0 ) {
			return IMG.GetD( IMG.I_MIDI_VELOCITY );
		} else {
			return new VelocityImage( ins );
		}
	}

	private Int127Menu menu ;
	
	@Override
	public void run() {
		if( menu==null || menu.isDisposed() ) {
			menu = new Int127Menu( SceneManager.getDefault().getScene(), M.SCENE_EDITOR_CONTROL );
			menu.addMenuSelectionListener( new MenuSelectionListener() {
				@Override
				public void menuEntrySelected(int id) {
					if( target instanceof IMidiInstrument ) {
						run( (IMidiVelocity)target, id );
					} else {
						for( Object o : (Collection<?>)target ) {
							run( (IMidiVelocity)o, id );
						}
					}
				}
			});
			//choose scene center 
			Point sz = SceneManager.getDefault().getScene().getSize();
			menu.open( sz.x/2, sz.y/2 );
		} else {
			menu.close();
		}
	}
	
	protected void run( IMidiVelocity c, int velocity ) {
		c.setMidiVelocity( velocity );
	}

	private static class VelocityImage implements IDrawable
	{
		int velocity;
		private IDrawable img;
		
		VelocityImage( int p ) { 
			velocity=p;
			img = IMG.GetD( IMG.I_MIDI_VELOCITY );
		}
		@Override
		public Point computeSize(int width, int height) {
			Point sz = img.computeSize( width, height );
			GC gc = SceneManager.getDefault().getScene().getGC();
			gc.setFont( FontManager.getInstance().getToolBarFont() );
			Point st = gc.textExtent( Integer.toString(velocity) );
			sz.x += 5+st.x;
			sz.y = Math.max( sz.y, st.y );
			return sz;
		}

		@Override
		public void paint( GC gc, int x, int y, int width, int height, int state ) {
			
			gc.setFont( FontManager.getInstance().getToolBarFont() );
			String txt = Integer.toString(velocity);
			Point st = gc.textExtent( txt );
			
			int xt = x+width-st.x;
			int yt = y+(height-st.y)/2;
			
			gc.setForeground( COLOR.grey0 );
			gc.drawText( txt, xt, yt, true );
			
			img.paint( gc, x, y, width-5-st.x, height, state );
		}
		
	}
}